
#include "stdafx.h"
#include <assert.h>
#include "MessageData.h"

MessageData::MessageData(int queue_size) 
: head_(0),
  tail_(0),
  queue_size_(queue_size)
{
	pBuffer_	 = new byte[queue_size_];
	memset(pBuffer_, 0, queue_size_);
}

MessageData::~MessageData()
{
	
}

void MessageData::release()
{
	tail_ = head_ = queue_size_ = 0;
	delete [] pBuffer_;
}

void MessageData::wr_ptr(size_t size)
{
	tail_  = (tail_ + size) % queue_size_;
}

void MessageData::rd_ptr(size_t size)
{
	head_ = (head_ + size)  % queue_size_;
}

void* MessageData::wr_ptr() 
{ 
	return pBuffer_ + tail_; 
}

void* MessageData::rd_ptr() 
{ 
	return pBuffer_ + head_; 
}

inline size_t MessageData::check_data_size()
{
	return (head_ <= tail_) ? 
		tail_ - head_ : queue_size_ - (head_+tail_);
}

inline size_t MessageData::check_queue_size()
{
	return queue_size_;
}

inline size_t MessageData::check_queue_empty()
{
	return check_queue_size() - check_data_size();
}

int MessageData::enqueue(byte* pData, size_t en_size)
{	
		if( check_queue_empty() < en_size) 
			return -1;

		if(head_ > tail_)
		{
			memcpy(this->wr_ptr(),  pData,  en_size);
		}
		else // head <= tail_
		{
			size_t right_free_size = queue_size_ - tail_;
			int wr_size = min(right_free_size, en_size);

			memcpy(this->wr_ptr(), pData, wr_size);

			int remain_data_size = en_size - wr_size;
			if(0 < remain_data_size)
			{
				assert(tail_ == 0);
				memcpy(this->wr_ptr(), pData + wr_size, remain_data_size);
			}
		}

	return 0;
}

int MessageData::dequeue(byte* pData, size_t rd_size)
{
	if(!this->check_queue_empty())
	{
		return 1;
	}

	if(head_ < tail_)
	{
		memcpy(pData, this->rd_ptr(),  rd_size);
		this->rd_ptr(rd_size);
	}
	else
	{
		size_t head_right_size = min(rd_size, queue_size_ - head_);

		memcpy(pData, this->rd_ptr(), head_right_size);
		this->rd_ptr(head_right_size);

		int remain_read_size = rd_size - head_right_size;
		if(0 < remain_read_size)
		{
			assert(0 == head_);
			memcpy(pData, this->rd_ptr(), remain_read_size);
			this->rd_ptr(remain_read_size);
		}
	}

	return 0;
}


